home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / dev / lang / sofa.lha / sofa / smalleiffel / lib_se / conversion_handler.e < prev    next >
Text File  |  2000-03-25  |  13KB  |  394 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr
  4. --                       http://SmallEiffel.loria.fr
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License
  11. -- for  more  details.  You  should  have  received a copy of the GNU General
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. class CONVERSION_HANDLER
  17.    --
  18.    -- Singleton object used to handle allowed automatic conversion from 
  19.    -- Eiffel type to another Eiffel type.
  20.    -- This singleton is shared via the GLOBALS.`conversion_handler' once function.
  21.    --
  22.  
  23. inherit GLOBALS;
  24.  
  25. feature 
  26.    
  27.    implicit_cast(expression: EXPRESSION; destination_type: TYPE): EXPRESSION is
  28.          -- If necessary, wrap `expression' inside an IMPLICIT_CAST invisible 
  29.          -- wrapper object.
  30.       require
  31.          expression.result_type.is_a(destination_type)
  32.       local
  33.          source_bit, destination_bit: TYPE_BIT;
  34.       do
  35.          source := expression.result_type
  36.          if source.run_time_mark = destination_type.run_time_mark then
  37.             Result := expression;
  38.          elseif source.is_reference then
  39.             if destination_type.is_reference then
  40.                -- Reference to Reference :
  41.                Result := expression;
  42.                generic_cast(destination_type);
  43.             else
  44.                -- Reference to Expanded :
  45.                !IMPLICIT_CAST!Result.make(expression,destination_type);
  46.             end;
  47.          elseif destination_type.is_reference then
  48.             -- Expanded to Reference :
  49.             computes_for(source,destination_type);
  50.             !IMPLICIT_CAST!Result.make(expression,destination);
  51.          else
  52.             -- Expanded to Expanded :
  53.             if destination_type.is_real and then source.is_integer then
  54.                -- INTEGER to REAL :
  55.                !IMPLICIT_CAST!Result.make(expression,destination_type);
  56.             elseif destination_type.is_double then
  57.                if source.is_integer or else source.is_real then
  58.                   -- INTEGER to DOUBLE or REAL to DOUBLE :
  59.                   !IMPLICIT_CAST!Result.make(expression,destination_type);
  60.                else
  61.                   Result := expression;
  62.                end;
  63.             elseif destination_type.is_bit then
  64.                source_bit ?= source.run_type;
  65.                destination_bit ?= destination_type.run_type;
  66.                if source_bit.nb /= destination_bit.nb then
  67.                   !IMPLICIT_CAST!Result.make(expression,destination_type);
  68.                else
  69.                   Result := expression;
  70.                end;
  71.             else
  72.                Result := expression;
  73.                generic_cast(destination_type);
  74.             end;
  75.          end;
  76.       ensure
  77.          Result /= Void
  78.       end;
  79.    
  80. feature {IMPLICIT_CAST}
  81.    
  82.    notify(expression: EXPRESSION; source_type, destination_type: TYPE) is
  83.          -- Notify some really needed conversion of `expression' from 
  84.          -- some `source_type' to some `destination_type'.
  85.       require
  86.          source_type.run_time_mark /= destination_type.run_time_mark;
  87.          source_type.is_expanded or destination_type.is_expanded
  88.       do
  89.          computes_for(source_type,destination_type);
  90.          if source_types.has(entry) then
  91.             source := source_types.at(entry);
  92.             if not source.is_a(source_type) then
  93.                eh.cancel;
  94.                source_types.put(source_type,entry);
  95.                expressions.put(expression,entry);
  96.             end;
  97.          else
  98.             if source.is_expanded then
  99.                destination.run_class.set_at_run_time;
  100.             end;
  101.             source_types.put(source_type,entry);
  102.             destination_types.put(destination_type,entry);
  103.             if expression /= Void then
  104.                expressions.put(expression,entry);
  105.             end;
  106.             -- *** To DEBUG ***
  107. --            if true then
  108. --               eh.append("CONVERSION_HANDLER.Notify : ");
  109. --               eh.append(entry);
  110. --               eh.append(" originally: from ");
  111. --               eh.append(source_type.run_time_mark);
  112. --               eh.append(" to ");
  113. --               eh.append(destination_type.run_time_mark);
  114. --               if expression /= Void then
  115. --                  eh.add_position(expression.start_position);
  116. --               end;
  117. --               eh.print_as_warning;
  118. --            end;
  119.             --
  120.          end;
  121.       end;
  122.  
  123. feature {SWITCH, FORMAL_ARG_LIST, E_STRIP}
  124.  
  125.    passing(source_type, destination_type: TYPE) is
  126.       do
  127.          if source_type.is_expanded then
  128.             if destination_type.is_reference then
  129.                notify(Void,source_type,destination_type);
  130.             end;
  131.          elseif destination_type.is_expanded then
  132.             notify(Void,source_type,destination_type);
  133.          else
  134.             source := source_type;
  135.             generic_cast(destination_type);
  136.          end;
  137.       end;
  138.  
  139. feature {IMPLICIT_CAST,C_PRETTY_PRINTER,E_STRIP}
  140.  
  141.    c_function_call(source_type, destination_type: TYPE) is
  142.       do
  143.          computes_for(source_type,destination_type);
  144.          if source.run_time_mark /= destination.run_time_mark then
  145.             cpp.put_character('T');
  146.             cpp.put_integer(source.id);
  147.             cpp.put_string(fz_to_t);
  148.             cpp.put_integer(destination.id);
  149.             cpp.put_character('(');
  150.          else
  151.             cpp.put_string("/*NO_CONVERSION*/(");
  152.          end;
  153.       end;
  154.  
  155. feature {C_PRETTY_PRINTER}
  156.  
  157.    c_definitions is
  158.       local
  159.          i: INTEGER;
  160.       do
  161.          from
  162.             i := 1;
  163.          until
  164.             i > source_types.count
  165.          loop
  166.             source := source_types.item(i);
  167.             entry := source_types.key(i);
  168.             destination := destination_types.at(entry);
  169.             computes_for(source,destination);
  170.             if source.is_bit then
  171.                c_function_definition;
  172.             elseif source.is_expanded and then destination.is_expanded then
  173.                -- Because it is worthless or already done with #define in 
  174.                -- "SmallEiffel/sys/runtime/base.h".
  175.             else
  176.                c_function_definition;
  177.             end;
  178.             i := i + 1;
  179.          end;
  180.       end;
  181.  
  182. feature {SMALL_EIFFEL}
  183.  
  184.    finish_falling_down is
  185.       local
  186.          i: INTEGER;
  187.          source_type, destination_type: TYPE;
  188.          rc1, rc2: RUN_CLASS;
  189.       do
  190.          from
  191.             i := 1;
  192.          until
  193.             i > source_types.count
  194.          loop
  195.             source_type := source_types.item(i);
  196.             entry := source_types.key(i);
  197.             destination_type := destination_types.at(entry);
  198.             computes_for(source_type,destination_type);
  199.             if source.is_reference then
  200.                if destination.is_expanded then
  201.                   echo.put_string(entry);
  202.                   echo.put_string(" (");
  203.                   echo.put_string(source_type.run_time_mark);
  204.                   echo.put_string(fz_to);
  205.                   echo.put_string(destination_type.run_time_mark);
  206.                   echo.put_string(")%N");
  207.                   small_eiffel.reference_to_expanded(source_type);
  208.                end;
  209.             end;
  210.             if source.is_user_expanded then
  211.                if destination.is_reference then
  212.                   rc1 := source.run_class;
  213.                   rc2 := destination.run_class;
  214.                end;
  215.             elseif destination.is_user_expanded then
  216.                if source.is_reference then
  217.                   rc1 := source.run_class;
  218.                   rc2 := destination.run_class;
  219.                end;
  220.             end;
  221.             if rc1 /= Void then
  222.                rc1.shared_attributes(rc2);
  223.                rc2.shared_attributes(rc1);
  224.                rc1 := Void;
  225.             end;
  226.             i := i + 1;
  227.          end;
  228.       end;
  229.  
  230. feature {NONE}
  231.  
  232.    source, destination: TYPE;
  233.          -- Temporary memory to store actual `source' and `destination' type.
  234.  
  235.    entry: STRING;
  236.          -- Temporary memory to store the `entry' in dictionaries.
  237.  
  238.    computes_for(source_type, destination_type: TYPE) is
  239.          -- Compute actual `source' and `destination' as well as the 
  240.          -- corresponding `entry' used for dictionaries.
  241.       require
  242.          source_type.is_expanded or destination_type.is_expanded
  243.       do
  244.          if source_type.is_expanded then
  245.             source := source_type;
  246.             if destination_type.is_expanded then
  247.                destination := destination_type;
  248.             else
  249.                destination := source.actual_reference(destination_type);
  250.             end;
  251.          else
  252.             destination := destination_type;
  253.             source := destination.actual_reference(source_type);
  254.          end;
  255.          buffer.clear;
  256.          buffer.append(source.run_time_mark);
  257.          buffer.append(fz_to);
  258.          buffer.append(destination.run_time_mark);
  259.          entry := string_aliaser.item(buffer);
  260.       end;
  261.  
  262.    source_types: DICTIONARY[TYPE,STRING] is
  263.          -- All source types available from some `entry'.
  264.       once
  265.          !!Result.make;
  266.       end;
  267.  
  268.    destination_types: DICTIONARY[TYPE,STRING] is
  269.          -- All destination types available from `entry'.
  270.       once
  271.          !!Result.make;
  272.       end;
  273.  
  274.    expressions: DICTIONARY[EXPRESSION,STRING] is
  275.          -- This dictionary is used to warn the user about some 
  276.          -- unwanted implicit objects allocation.
  277.          -- Also use the same `entry' access key.
  278.       once
  279.          !!Result.make;
  280.       end;
  281.  
  282.    c_function_definition is
  283.          -- Called to produce the C convertion function for `entry', `source' 
  284.          -- and `destination'.
  285.       require
  286.          source.run_time_mark /= destination.run_time_mark
  287.       local
  288.      rc: RUN_CLASS;
  289.       do
  290.          echo.put_string("Conversion from ");
  291.          echo.put_string(entry);
  292.          echo.put_string(" in C function ");
  293.          buffer.clear;
  294.          destination.c_type_for_result_in(buffer);
  295.          buffer.extend(' ');
  296.          buffer.extend('T');
  297.          source.id.append_in(buffer);
  298.          buffer.append(fz_to_t);
  299.          destination.id.append_in(buffer);
  300.          buffer.extend('(');
  301.          source.c_type_for_argument_in(buffer)
  302.          buffer.append(" source)");
  303.          echo.put_string(buffer);
  304.          echo.put_string(fz_b6);
  305.          if destination.is_expanded then
  306.             if source.is_expanded then
  307.            -- expanded to expanded :
  308.                buffer.copy("#define T");
  309.                source.id.append_in(buffer);
  310.                buffer.append(fz_to_t);
  311.                destination.id.append_in(buffer);
  312.                buffer.append("(x) (x)%N");
  313.                cpp.put_string_on_h(buffer);
  314.             else
  315.            -- reference to expanded :
  316.                cpp.put_c_heading(buffer);
  317.                buffer.copy("return (((");
  318.                source.c_type_for_target_in(buffer);
  319.                buffer.append(")source)->_item);%N");
  320.                cpp.put_string(buffer);
  321.                cpp.put_string(fz_12);
  322.             end;
  323.          else
  324.         -- expanded to reference :
  325.             cpp.put_c_heading(buffer);
  326.             cpp.put_character('T');
  327.             cpp.put_integer(destination.id);
  328.             cpp.put_character('*');
  329.         rc := destination.run_class;
  330.             gc_handler.allocation_of("destination",rc);
  331.         if source.is_basic_eiffel_expanded then
  332.            cpp.put_string("destination->_item=source;%N");
  333.         else
  334.            cpp.put_string("memcpy((((Tid*)destination)");
  335.            if rc.is_tagged then
  336.           cpp.put_string("+1");
  337.            end;
  338.            cpp.put_string("),&source,sizeof(source));%N");
  339.         end;
  340.             cpp.put_string("return ((T0*)destination);%N}%N");
  341.          end;
  342.       end;
  343.  
  344.    generic_cast(destination_type: TYPE) is
  345.       local
  346.          s_gl, d_gl: ARRAY[TYPE];
  347.          s, d: TYPE;
  348.          i, j: INTEGER;
  349.       do
  350.          if source.is_generic and then destination_type.is_generic then
  351.             s_gl := source.generic_list;
  352.             d_gl := destination_type.generic_list;
  353.             from
  354.                i := s_gl.upper;
  355.             until
  356.                i = 0
  357.             loop
  358.                from
  359.                   j := d_gl.upper;
  360.                   s := s_gl.item(i);
  361.                until
  362.                   j = 0
  363.                loop
  364.                   d := d_gl.item(j);
  365.                   if d.is_a(s) then
  366.                      passing(d,s);
  367.                   else
  368.                      eh.cancel;
  369.                   end;
  370.                   j := j - 1;
  371.                end;
  372.                i := i - 1;
  373.             end;
  374.          end;
  375.       end;
  376.  
  377.    buffer: STRING is
  378.       once
  379.          !!Result.make(128);
  380.       end;
  381.  
  382.    fz_to: STRING is " to ";
  383.  
  384.    singleton_memory: CONVERSION_HANDLER is
  385.       once
  386.          Result := Current;
  387.       end;
  388.  
  389. invariant
  390.  
  391.    is_real_singleton: Current = singleton_memory
  392.  
  393. end -- CONVERSION_HANDLER
  394.